package com.decent.common.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;

/**
 * 签名校验工具
 *
 * @author wangyan
 */
@SuppressWarnings("Duplicates")
@Slf4j
public class SignUtil {
    /**
     * 传递实体类 值非空的话按键的ASCII码升序拼接k=v&k1=v1&key=value 进行拼接
     *
     * @param t               实体类
     * @param key             key
     * @param humpToUnderline 键是否由驼峰转成下划线拼接
     * @param ignoreKeys      拼装签名的时候忽略的键
     * @return : java.lang.String
     */
    public static <T> String buildSign(T t, String key, boolean humpToUnderline, List<String> ignoreKeys) {
        if (Objects.isNull(t) || StrUtil.isBlank(key)) {
            return "";
        }
        StringBuilder sb = new StringBuilder(100);
        try {
            Map<String, Object> map = BeanUtil.beanToMap(t);
            TreeMap<String, Object> treeMap = new TreeMap<>(map);
            String classType = "class";
            String sign = "sign";
            boolean flag = Objects.nonNull(ignoreKeys) && !ignoreKeys.isEmpty();
            treeMap.forEach((k, v) -> {
                if (!StrUtil.equals(classType, k) && !StrUtil.equals(sign, k) && Objects.nonNull(v)) {
                    if (!flag || !ignoreKeys.contains(k)) {
                        sb.append(humpToUnderline ? StringHelpers.humpToUnderline(k) : k);
                        sb.append("=");
                        sb.append(v);
                        sb.append("&");
                    }
                }
            });
            sb.append("key");
            sb.append("=");
            sb.append(key);
        } catch (Exception e) {
            log.error("buildSign Object [{}] and sign [{}] error", JSONUtil.toJsonStr(t), key, e);
            return "";
        }
        return sb.toString();
    }

    /**
     * 传递实体类 值非空的话按键的ASCII码升序拼接k=v&k1=v1 进行拼接
     *
     * @param t               实体类
     * @param humpToUnderline 键是否由驼峰转成下划线拼接
     * @param ignoreKeys      拼装签名的时候忽略的键
     * @return : java.lang.String
     */
    public static <T> String buildSignWithoutKey(T t, boolean humpToUnderline, List<String> ignoreKeys) {
        if (Objects.isNull(t)) {
            return "";
        }
        StringBuilder sb = new StringBuilder(100);
        try {
            Map<String, Object> map = BeanUtil.beanToMap(t);
            TreeMap<String, Object> treeMap = new TreeMap<>(map);
            String classType = "class";
            String sign = "sign";
            boolean flag = Objects.nonNull(ignoreKeys) && !ignoreKeys.isEmpty();
            treeMap.forEach((k, v) -> {
                if (!StrUtil.equals(classType, k) && !StrUtil.equals(sign, k) && Objects.nonNull(v)) {
                    if (!flag || !ignoreKeys.contains(k)) {
                        sb.append(humpToUnderline ? StringHelpers.humpToUnderline(k) : k);
                        sb.append("=");
                        sb.append(v);
                        sb.append("&");
                    }
                }
            });
        } catch (Exception e) {
            log.error("buildSign Object [{}] error", JSONUtil.toJsonStr(t), e);
            return "";
        }
        return StrUtil.removeSuffix(sb.toString(), "&");
    }

    /**
     * 校验接口传递的时间戳是否与系统时间相差指定的毫秒值
     *
     * @param timestamp      接口传递的时间戳
     * @param timeDifference 指定的毫秒值
     * @return : boolean
     */
    public static boolean checkTimestampCorrect(Long timestamp, int timeDifference) {
        return Math.abs(System.currentTimeMillis() - timestamp) <= timeDifference;
    }
}
